package com.hcss.common.shiro.session;

import com.hcss.common.constant.CommonConstants;
import com.hcss.common.shiro.ShiroProperties;
import com.hcss.common.util.SerializeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.SimpleSession;
import org.apache.shiro.session.mgt.ValidatingSession;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.util.Collection;

/**
 * @描述: shiro session与redis交互，直接从redis中取session，不使用本地缓存
 * @作者: xuqian
 * @创建日期: 2018-07-17 9:33
 * @公司 浙江鸿程计算机系统有限公司
 */
@Repository
@Slf4j
public class ShiroRedisSessionDAO extends AbstractSessionDAO {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ShiroProperties shiroProperties;

    @Override
    protected Serializable doCreate(Session session) {
        Serializable sessionId = generateSessionId(session);
        assignSessionId(session, sessionId);
        String key = getRedisKey(sessionId.toString());
        String value = SerializeUtils.serializeToString((SimpleSession)session);
        redisTemplate.opsForValue().set(key, value, shiroProperties.getRedis().getExpireTime(), ShiroProperties.Redis.UNIT);
        return sessionId;
    }

    @Override
    protected Session doReadSession(Serializable sessionId) {
        if(sessionId == null){
            throw new NullPointerException("id argument cannot be null.");
        }
        String key = getRedisKey(sessionId.toString());
        String value = redisTemplate.opsForValue().get(key);
        if (StringUtils.isBlank(value)) {
            return null;
        }
        Session session = SerializeUtils.deserializeFromString(value);
        return session;
    }

    @Override
    public void update(Session session) throws UnknownSessionException {
        try {
            if (session instanceof ValidatingSession && !((ValidatingSession) session).isValid()) {
                return;
            }
        } catch (Exception e) {
            log.error("ValidatingSession error");
        }

        String key = getRedisKey(session.getId().toString());
        String value = SerializeUtils.serializeToString((SimpleSession)session);
        redisTemplate.opsForValue().set(key, value, shiroProperties.getRedis().getExpireTime(), ShiroProperties.Redis.UNIT);
    }

    @Override
    public void delete(Session session) {
        if(session == null || session.getId() == null){
            log.error("session or session id is null");
            return;
        }
        redisTemplate.delete(getRedisKey(session.getId().toString()));
    }

    @Override
    public Collection<Session> getActiveSessions() {
        String keys = shiroProperties.getRedis().getNamePrefix() + CommonConstants.STAR;
        return SerializeUtils.deserializeFromStringController(redisTemplate.keys(keys));
    }

    /**
     * 获取session在redis中key值
     *
     * @param sessionId
     * @return
     */
    private String getRedisKey(String sessionId) {
        return shiroProperties.getRedis().getNamePrefix() + CommonConstants.COLON + sessionId;
    }

}
